package com.ken.algorithms.linkedList;

import java.util.Arrays;

/**
 * <ul>
 * <li>Title: MyList</li>
 * <li>Description: TODO </li>
 * </ul>
 *
 * @author 程序员ken
 * @date 2021/5/20 0020 下午 12:56
 */
public class MyList<E> {

    private static final int DEFAULT_CAPACITY = 10;

    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    transient Object[] elementData;

    //数组长度
    private  int size = 0;

    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;


    public MyList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }


    public void add(E e){

        if(this.elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA){
            this.elementData = new Object[DEFAULT_CAPACITY];
        }

        //当前新增 超出元素个数
        if(size+1>this.elementData.length){
            // 超出元素 每次扩容10
            //Object[] objects = new Object[DEFAULT_CAPACITY + this.elementData.length];

            // 如果没有这个扩容  后面 操作对象的频率就很高 消耗内存就会急剧增加
            int newCapacity  = this.elementData.length + (this.elementData.length >> 1);//右移一位相当于除以2

            if(MAX_ARRAY_SIZE < newCapacity){
                throw new RuntimeException("超出容器最大容量");
            }

            else if(size+1>newCapacity){
                newCapacity = size+1;
            }

//            if(MAX_ARRAY_SIZE< DEFAULT_CAPACITY + this.elementData.length){
//                throw new RuntimeException("超出容器最大容量");
//            }
//           for (int i = 0; i <this.elementData.length ; i++) {
//                objects [i] = this.elementData[i];
//            }
//            this.elementData = objects;

            this.elementData =  Arrays.copyOf(this.elementData, newCapacity);
        }
        this.elementData[size++]=e;
    }


    //移除数组
    public E remove(int index) {
        rangeCheck(index);

        //modCount++;
        E oldValue = (E) this.elementData[index];;

        int numMoved = size - index - 1;
        if (numMoved > 0){
            System.arraycopy(elementData, index+1, elementData, index,
                    numMoved);
        }

        elementData[--size] = null; // clear to let GC do its work

        return oldValue;
    }

    public E get(int  index){
        rangeCheck(index);
        return (E)elementData[index];
    }

    //范围检查
    private void rangeCheck(int index) {
        if (index >= size){
            throw new IndexOutOfBoundsException(String.format("Index:%s, Size:%s",index,this.size));
        }
    }

    private int size() {
        return  this.size;
    }

    public static void main(String[] args) {
        MyList myList = new MyList();
        for (int i = 0; i <10000000 ; i++) {
            myList.add(i);
        }
//        for (int i = 0; i <myList.size ; i++) {
//            System.out.println(myList.get(i));
//        }

        System.out.println(myList.size());




    }


}
